<template>
    <div id="map-container" ref="mapContainer"></div>
</template>

<script setup>
import { onMounted, ref, defineProps, watch } from 'vue';
import { getCityByIP, getAdcodeByCity, getGeoJSONByAdcode } from '@/api/index.js'
import Map from "ol/Map";
import "ol/ol.css";
import { Cluster, XYZ } from "ol/source";
import View from "ol/View";
import TileLayer from "ol/layer/Tile";
import Style from 'ol/style/Style';
import Stroke from 'ol/style/Stroke';
import Fill from 'ol/style/Fill';
import GeoJSON from "ol/format/GeoJSON.js";
import VectorSource from 'ol/source/Vector';
import VectorLayer from 'ol/layer/Vector';
import Draw from "ol/interaction/Draw.js";
import Icon from 'ol/style/Icon';
import { unByKey } from 'ol/Observable';
import { Feature } from 'ol';
import { Point } from 'ol/geom';
import CircleStyle from "ol/style/Circle.js";
import Text from "ol/style/Text.js";
import {Overlay} from 'ol';
import { getLength } from 'ol/sphere';

const props = defineProps({
    targetAdcode: String,
    drawType:String,
    resetDrawType:Function,
    markType:String,
    resetMarkType:Function,
    disableMarkSelect:Boolean,
})

const mapContainer = ref(null);
let map = null;
let vectorLayer = null;
let drawInteraction = null;
let clickListenerKey = null;
let measureOverlay = new Overlay({});

const MIN_ZOOM_FOR_HIGHLIGHT = 8;
const MAX_ZOOM_FOR_HIGHLIGHT = 11;

const emit = defineEmits(['zoom-changed'])

// 样式配置
const highlightStyle = new Style({
    stroke: new Stroke({
        color: 'red',
        width: 3,
    }),
    fill: new Fill({
        color: 'rgba(255,0,0,0.3)'
    })
})

// 高亮指定城市（统一处理本地和搜索城市）
const highlightCity = async (adcode) => {
    if (!adcode) return;
    
    try {
        const geoJSON = await getGeoJSONByAdcode(adcode);
        const format = new GeoJSON();
        const features = format.readFeatures(geoJSON);

        if (features.length > 0) {
            const geometry = features[0].getGeometry();
            const center = geometry.getExtent();
            const centerCoords = [
                (center[0] + center[2]) / 2,
                (center[1] + center[3]) / 2
            ];

            // 动画效果
            map.getView().animate({
                center: centerCoords,
                zoom: MIN_ZOOM_FOR_HIGHLIGHT,
                duration: 1000
            });

            // 清除旧图层
            if (vectorLayer) {
                map.removeLayer(vectorLayer);
            }

            // 创建新图层
            const source = new VectorSource({ features });
            vectorLayer = new VectorLayer({
                source,
                style: highlightStyle
            });

            map.addLayer(vectorLayer);
            updateHighlightVisibility();
        }
    } catch (error) {
        console.error('高亮城市失败:', error);
        await loadLocalCity();//回到本地城市
    }
};

// 更新高亮层可见性范围
const updateHighlightVisibility = () => {
    if (vectorLayer) {
        const currentZoom = map.getView().getZoom();
        vectorLayer.setVisible(
            currentZoom >= MIN_ZOOM_FOR_HIGHLIGHT && 
            currentZoom <= MAX_ZOOM_FOR_HIGHLIGHT
        );
    }
};

// 加载本地城市
const loadLocalCity = async () => {
    try {
        const IPRes = await getCityByIP();
        const localCityAdcode = IPRes.adcode;
        highlightCity(localCityAdcode);
    } catch (error) {
        console.error('加载本地城市失败:', error);
    }
};

//绘图图层源
const drawSource = new VectorSource();
const drawLayer = new VectorLayer({
    source:drawSource,
    style:new Style({
        stroke:new Stroke({
            color:'blue',
            width:2,
        })
    })
})

//清除现有绘制交互
const clearDrawInteraction = () => {
    if(drawInteraction) {
        map.removeInteraction(drawInteraction);
        drawInteraction = null;
        map.removeOverlay(measureOverlay);//清除覆盖层
    }
}

//初始化不同类型的绘图交互
const drawInteractions = (type,freehand = false) => {
    clearDrawInteraction();

    drawInteraction = new Draw({
        source:drawSource,
        type:type,
        freehand:freehand,//控制自由线段
        // maxPoints:maxpoints,
        style:new Style({
            stroke:new Stroke({
                color:'rgba(0,0,255,0.7)',
                width:2,
            })
        })
    })

    //监听绘制完成事件
    drawInteraction.on('drawend',(e)=>{
        const feature = e.feature;
        const geometry = feature.getGeometry();
        const geometryType = geometry.getType();

        //如果是直线，添加测距功能
        if(geometryType === 'LineString') {
            // const measureOverlay = new Overlay({});
            const overlayDom = document.createElement('div');
            overlayDom.className = 'overlay';
            document.body.appendChild(overlayDom);
            measureOverlay.setElement(overlayDom);
            map.addOverlay(measureOverlay);

            let length = getLength(geometry, { projection: 'EPSG:4326' })
            length = (length / 1000).toFixed(1);
            overlayDom.innerHTML = "距离是：" + length + 'km';
            let coordinate = geometry.getCoordinates()[geometry.getCoordinates().length - 1];
            measureOverlay.setPosition(coordinate)
        }

    })

    map.addInteraction(drawInteraction);
}

//标记点样式
const getMarkerStyle = (type) => {
    return new Style({
        image:new Icon({
            src:`../../../public/${type}.png`,
            anchor:[0.5,1],
            scale:0.5,
        })
    })
}

//监听视图变化-改变el-select的选中状态
const checkZoomLevel = () => {
    // if (!map) return;

    const currentZoom = map.getView().getZoom();
    const shouldDisable = currentZoom <= 13;
    // console.log(shouldDisable)

    emit('zoom-changed',shouldDisable);
}

let clusterLayer = null;
let clusterSource = null;

const createClusterLayer = () =>{

// 创建专用于聚合的点数据源
const pointSource = new VectorSource();

// 创建聚合数据源（只包含点要素）
clusterSource = new Cluster({
  source: pointSource,  // 使用过滤后的点数据源
  distance: 40
});

clusterLayer = new VectorLayer({
  source: clusterSource,
  style: clusterStyle(),
  zIndex:999,
});
map.addLayer(clusterLayer);

 // 监听绘图数据源变化，更新聚合图层
  drawSource.on('addfeature', updateClusterFeatures);
  drawSource.on('removefeature', updateClusterFeatures);
}

function clusterStyle() {
  return (f) => {
    const size = f.get("features").length;
    let style = new Style();
      style.setImage(
        new CircleStyle({
          radius: 10,
          stroke: new Stroke({
            color: "#fff",
          }),
          fill: new Fill({
            color: "#3399CC",
          }),
        })
      );
      style.setText(
        new Text({
          text: size.toString(),
          fill: new Fill({
            color: "#fff",
          }),
        })
      );
    
    return style;
  };
}

// 更新聚合图层的要素
const updateClusterFeatures = () => {
  if (!clusterSource) return;
  
  // 获取原始矢量图层的所有要素
  const allFeatures = drawSource.getFeatures();

  // 过滤出只有点要素的数组
  const pointFeatures = allFeatures.filter(feature => 
    feature.getGeometry().getType() === 'Point'
  );
  
  // 更新聚合数据源
  clusterSource.getSource().clear();
  clusterSource.getSource().addFeatures(pointFeatures);
}


onMounted(() => {
    map = new Map({
        target: mapContainer.value,
        view: new View({
            center: [114.27, 30.59],
            projection: "EPSG:4326",
            zoom: 4,
        }),
        layers: [
            new TileLayer({
                source: new XYZ({
                    url: "http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}",
                }),
            }),
        ],
    });

    // 监听分辨率变化
    map.getView().on('change:resolution', updateHighlightVisibility);

    // 监听搜索城市props变化
    watch(() => props.targetAdcode, (newAdcode) => {
        if (newAdcode) {
            highlightCity(newAdcode);
        } else {
            // 如果没有传入adcode，则显示本地城市
            loadLocalCity();
        }
    });

    //监听绘图类型的变化
    watch(() => props.drawType,(newType) => {
        switch(newType){
            case 'line':
                drawInteractions('LineString');
                break;
            case 'circle':
                drawInteractions('Circle');
                break;
            case 'polygon':
                drawInteractions('Polygon');
                break;
            case 'freedraw':
                drawInteractions('LineString',true);
                break;
            case 'clear':
                drawSource.clear();
                if(props.resetDrawType) {
                    props.resetDrawType();
                }
                break;
            default:
                clearDrawInteraction();
        }
    })

    map.addLayer(drawLayer);

    //创建聚合图层
    createClusterLayer();

    //监听标记类型变化
    watch(() => props.markType,(newType) => {
        if(clickListenerKey) {
            unByKey(clickListenerKey);
            clickListenerKey = null;
        }

        if(!newType) {
            if(props.resetMarkType){
                props.resetMarkType();
            }
            return;
        }

        clickListenerKey = map.on('click',(e) => {
            const feature = new Feature({
                geometry:new Point(e.coordinate),
            });
            feature.setStyle(getMarkerStyle(newType));
            drawSource.addFeature(feature);
        })
    })

    //初始化检查
    checkZoomLevel();

    //添加分辨率监听
    map.getView().on('change:resolution',checkZoomLevel);

    // 初始加载
    loadLocalCity();
});
</script>

<style scoped>
#map-container {
    width: 100%;
    height: calc(100vh - 60px);
}
</style>